package edu.uclmgmu.bacteriosec.aspects.sos;

import java.io.FileOutputStream;
import edu.uclmgmu.bacteriosec.aspects.common.*;

privileged aspect SOS_OMOInterchange {
	
	private byte[] firstMessage;

	void around(java.io.FileOutputStream f, byte[] b) : target(f) && args(b) &&  call(* FileOutputStream.write(byte[])) {
		int numberOfCurrentCall=Store.get(thisJoinPointStaticPart.getSignature());
		int numberOfCallInTurn=Store.getNumberOfCallInTurn();
		if (numberOfCurrentCall==numberOfCallInTurn) {
			Store.log(this.getClass().getCanonicalName(), numberOfCurrentCall, thisJoinPointStaticPart.getSignature());
			Store.put(thisJoinPointStaticPart.getSignature(), ++numberOfCurrentCall);
			this.firstMessage=b;
			return;
		} else if (numberOfCurrentCall==numberOfCallInTurn+1) {
			Store.put(thisJoinPointStaticPart.getSignature(), ++numberOfCurrentCall);
			byte[] newMessage=new byte[b.length + this.firstMessage.length];
			int i=0;
			for (i=0; i<b.length; i++) {
				newMessage[i]=b[i];
			}
			for (int j=i; j<b.length+this.firstMessage.length; j++) {
				newMessage[j]=this.firstMessage[j-i];
			}
			this.firstMessage=null;
			b=newMessage;
			proceed(f, b);
			return;
		} else {
			Store.put(thisJoinPointStaticPart.getSignature(), ++numberOfCurrentCall);
			proceed(f, b);
		}
	}
	
	void around(java.io.FileOutputStream f, byte[] b, int off, int len) : target(f) && args(b, off, len) &&  call(* FileOutputStream.write(byte[], int, int)) {
		int counter=Store.get(thisJoinPointStaticPart.getSignature());
		System.out.println(thisJoinPointStaticPart.getSignature() + "-> " + counter);
		if (counter==0) {
			this.firstMessage=b;
			Store.put(thisJoinPointStaticPart.getSignature(), ++counter);
			return;
		} else if (counter==1) {
			Store.put(thisJoinPointStaticPart.getSignature(), ++counter);
			byte[] newMessage=new byte[b.length + this.firstMessage.length];
			int i=0;
			for (i=0; i<b.length; i++) {
				newMessage[i]=b[i];
			}
			for (int j=i; j<b.length+this.firstMessage.length; j++) {
				newMessage[j]=this.firstMessage[j-i];
			}
			this.firstMessage=null;
			b=newMessage;
			proceed(f, b, off, len);
			return;
		} else {
			proceed(f, b, off, len);
		}
	}
}
